package com.wnxy.sddfp.search.service.impl;
import com.google.common.collect.Lists;

import com.wnxy.sddfp.common.model.page.Pages;
import com.wnxy.sddfp.search.model.query.BorrowRecordSearchQuery;
import com.wnxy.sddfp.search.model.vo.BorrowRecordVo;
import com.wnxy.sddfp.search.service.ISearchService;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SearchServiceImpl implements ISearchService {

    // 添加了es启动器；自动配置生效
    // spring-boot-autoconfigure-2.3.2.RELEASE.jar包中的META-INF/spring.factories
    // 自动配置类：ElasticsearchDataAutoConfiguration
    // 自动配置类又导入了配置类ElasticsearchDataConfiguration
    // 在配置类中创建了ElasticsearchRestTemplate对象；所以我们开发时候直接注入就可以使用
    // SpringBoot自动配置
    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Override
    public Pages<BorrowRecordVo> searchBorrowRecord(BorrowRecordSearchQuery borrowRecordSearchQuery) {

        // 创建条件构造器
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();

        // 通过条件构造器的withQuery()查询，添加查询条件
        // 条件1：name，先做非空判断； org.springframework.util.StringUtils
        if (StringUtils.hasText(borrowRecordSearchQuery.getDescription())) {
            // termQuery 词条查询，搜索条件不会分词
            //builder.withQuery(QueryBuilders.termQuery("description", borrowRecordSearchQuery.getDescription()));
            builder.withQuery(QueryBuilders.matchQuery("description", borrowRecordSearchQuery.getDescription()));
        }
        if (borrowRecordSearchQuery.getStartPeriod() != null) {
            builder.withQuery(QueryBuilders.rangeQuery("period").gte(borrowRecordSearchQuery.getStartPeriod()));
        }
        if (borrowRecordSearchQuery.getEndPeriod() != null) {
            builder.withQuery(QueryBuilders.rangeQuery("period").lte(borrowRecordSearchQuery.getEndPeriod()));
        }
        if (StringUtils.hasText(borrowRecordSearchQuery.getName())) {
            builder.withQuery(QueryBuilders.matchQuery("name", borrowRecordSearchQuery.getName()));
        }


        // 分页
        Integer pageNo = borrowRecordSearchQuery.getPageNo();
        Integer pageSize = borrowRecordSearchQuery.getPageSize();
        builder.withPageable(PageRequest.of(pageNo-1,pageSize));
        // 排序字段：createdate,对应的是索引库的字段，不是数据库。现在查询与数据库无关了。
        builder.withSort(SortBuilders.fieldSort("createdate").order(SortOrder.DESC));

        // 执行es查询，查询索引库
        SearchHits<BorrowRecordVo> searchHits =
                elasticsearchRestTemplate.search(builder.build(), BorrowRecordVo.class);
        log.debug("拼接后的查询条件：{}",builder.build());

        long totalHits = searchHits.getTotalHits();
        log.debug("查询总记录数：{}",totalHits);

        // 保存查询结果
        //List<BorrowRecordVo> resultList = new ArrayList<>();
        // 获取结果
        //List<SearchHit<BorrowRecordVo>> list = searchHits.getSearchHits();
        //for (SearchHit<BorrowRecordVo> hit : list) {
        //    BorrowRecordVo borrowRecordVo = hit.getContent();
        //    resultList.add(borrowRecordVo);
        //}

        // 通过stream流的map方法实现对象与对象之间的转换映射：
        // 把SearchHit对象的getContent()返回的结果映射为集合的元素
        List<BorrowRecordVo> resultList =
                searchHits.getSearchHits().stream()
                        .map(SearchHit::getContent).collect(Collectors.toList());

        // 返回结果
        Pages<BorrowRecordVo> pages = new Pages<>();
        pages.setList(resultList);
        pages.setPageNum(pageNo);
        pages.setPageSize(pageSize);
        pages.setTotal(totalHits);
        return pages;
    }
}
